﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Network;
using Network.Messages.Nova;
using Providers.Nova.Modules;

namespace Providers.Nova.Client
{
    public class NovaProvider : Provider
    {
        public NovaProvider(NetworkPeer network)
            : base(network)
        {
        }

        public override void RegisterMessageHandlers()
        {
            Network.RegisterUnconnectedMessageHandler<ResponseIntroducerIntroductionCompletedMessage>(OnResponseIntroducerIntroductionCompletedMessageReceived);
            Network.OnNatTraversalSucceeded += new EventHandler<NatTraversedEventArgs>(Network_OnNatTraversalSucceeded);

            Network.RegisterUnconnectedMessageHandler<ResponseSelfMachineInfoMessage>(OnResponseSelfMachineInfoMessageReceived);

            Network.RegisterUnconnectedMessageHandler<ResponseNoManOnDutyRegistrationCompletedMessage>(OnResponseNoManOnDutyRegistrationCompletedMessageReceived);
        }

        private void OnResponseNoManOnDutyRegistrationCompletedMessageReceived(UnconnectedMessageEventArgs<ResponseNoManOnDutyRegistrationCompletedMessage> obj)
        {
            OnNoManOnDutyRegistrationCompletedEvent?.Invoke(this,
                new NoManOnDutyRegistStatusArgs() {Result = obj.Message.Result});
        }


        private void OnResponseSelfMachineInfoMessageReceived(UnconnectedMessageEventArgs<ResponseSelfMachineInfoMessage> e)
        {
            OnSeverInfoRecived?.Invoke(this, new SeverInfoArgs() { Novaid = e.Message.NovaId, Password = e.Message.Password, FlagConnected = true });
        }

        private void OnResponseIntroducerIntroductionCompletedMessageReceived(UnconnectedMessageEventArgs<ResponseIntroducerIntroductionCompletedMessage> e)
        {
            OnIntroductionCompleted?.Invoke(this, new IntroducerIntroductionCompletedEventArgs { Result = e.Message.ResponseResult, DenyReason = e.Message.DenyReason });
        }

        private DateTime _lastConnectTime = DateTime.Now;
        void Network_OnNatTraversalSucceeded(object sender, NatTraversedEventArgs e)
        {
            Trace.WriteLine("Client:  Network_OnNatTraversalSucceeded()");

            lock (syncLock)
            {
                // 目的：每对客户端和服务器间只能有一个连接,且在连接后1秒内不能连入其它连接。
                // 这样可以解决双重网络的接入或连续点击导致的多重连接问题
                // 因为连接是有时间的，只用Network.IsConnected判断并不安全
                // 所以只应该在客户端响应连接事件
                if (!Network.IsConnected && OutLockTime())
                {
                    _lastConnectTime = DateTime.Now;
                    Trace.WriteLine("Client:  Network_OnNatTraversalSucceeded()  [LOCKED]");

                    OnNatTraversalSucceeded?.Invoke(this, new NatTraversedEventArgs { From = e.From });

                    try
                    {
                        Network.Connect((e.From));
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }
            }
        }

     
        private bool OutLockTime()
        {
            var dist = DateTime.Now - _lastConnectTime;
            return dist.TotalMilliseconds > 1000;
        }

        // TODO: Refactor this
        private static object syncLock = new object();
        private static bool alreadySent = false;

        public event EventHandler<IntroducerIntroductionCompletedEventArgs> OnIntroductionCompleted;
        public event EventHandler<NatTraversedEventArgs> OnNatTraversalSucceeded;

        public event EventHandler<SeverInfoArgs> OnSeverInfoRecived;
        public event EventHandler<NoManOnDutyRegistStatusArgs> OnNoManOnDutyRegistrationCompletedEvent;
    }
}
